﻿using System;
using System.IO;

using SharpOSCAR.Base;

namespace SharpOSCAR.Snac
{
    /// <summary>
    /// The SNAC Header is a simple 10 byte header that contains the foodgroup, type,
    /// any high level flags, and the requestId. 
    /// </summary>
    /// <remarks>
    /// The FLAP Header will be immediately followed by the SNAC Header that describes
    /// what type of message it is for SNAC messages sent over FLAP.
    /// 
    /// The requestId is used to link up requests and replies and can also be used to
    /// determine the direction of traffic. A client should never set the high bit of 
    /// a requestId or use 0. The server will always set the high bit for its requestId
    /// unless it is a reply to a client query, in which case it will use the same
    /// requestId as the request. The flags field tells the client if for the same request
    /// there will be multiple replies and if there are any SNAC Header TLVs. 
    /// </remarks>
    public abstract class SNAC__Header : ProtocolData
    {
        private U16 _Foodgroup;
        /// <summary>
        /// Numeric value that represents the foodgroup the SNAC is in
        /// </summary>
        public ushort Foodgroup
        {
            get { return _Foodgroup.Value; }
            set { _Foodgroup.Value = value; }
        }

        private U16 _Type;
        /// <summary>
        /// Numeric value that represent the SNAC type
        /// </summary>
        public ushort Type
        {
            get { return _Type.Value; }
            set { _Type.Value = value; }
        }

        private U16 _Flags;
        /// <summary>
        /// These are the flags that let the client know details about the SNAC being received.
        /// </summary>
        public ushort Flags
        {
            get { return _Flags.Value; }
            set { _Flags.Value = value; }
        }

        private U32 _RequestID;
        /// <summary>
        /// Used to link requests and replies
        /// </summary>
        public uint RequestID
        {
            get { return _RequestID.Value; }
            set { _RequestID.Value = value; }
        }

        /// <summary>
        /// Gets/sets the SNAC payload of the packet
        /// </summary>
        public ProtocolData SnacPayload { get; set; }

        /// <summary>
        /// Initializes the SNAC header with the specified parameters
        /// </summary>
        /// <param name="foodgroup">SNAC foodgroup</param>
        /// <param name="type">SNAC type</param>
        /// <param name="flags">Flags</param>
        /// <param name="requestId">Request ID</param>
        public SNAC__Header(ushort foodgroup, ushort type, ushort flags, uint requestId)
        {
            _Foodgroup = new U16(foodgroup);
            _Type = new U16(type);
            _Flags = new U16(flags);
            _RequestID = new U32(requestId);
        }

        /// <summary>
        /// Converts the Snac header into a byte array
        /// </summary>
        /// <returns>Returns a byte array representing the Snac</returns>
        public override byte[] ToByteArray()
        {
            using (MemoryStream ms = new MemoryStream())
            {
                _Foodgroup.WriteToStream(ms);
                _Type.WriteToStream(ms);
                _Flags.WriteToStream(ms);
                _RequestID.WriteToStream(ms);

                if (SnacPayload != null)
                    SnacPayload.WriteToStream(ms);

                return ms.ToArray();
            }
        }
    }
}
